using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;

public class AtomDictionary<TKey, TValue>
{
    AtomLock m_Lock = new AtomLock();
    Dictionary<TKey, TValue> m_Dictionary = new Dictionary<TKey, TValue>();
    
    #if DEBUG
    public Dictionary<TKey, TValue> dictionary => m_Dictionary; 
    #endif
    
    public int Count
    {
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        get
        { 
            m_Lock. Lock();
            try
            {
                return m_Dictionary.Count;
            }
            catch (Exception e)
            {
                GameDebug.LogException(e); 
                return 0;
            }

            finally
            {
                m_Lock.UnLock();
            }
        }
    }
 
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public void Add(TKey key, TValue value)
    {
        m_Lock.Lock();
        try
        {
            m_Dictionary.Add(key, value);
        }
        catch (Exception e)
        {
            GameDebug.LogException(e); 
        }
        finally
        {
            m_Lock.UnLock();
        }
    }
    
    #if NETCOREAPP
    
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public bool TryAdd(TKey key, TValue value)
    {
        m_Lock.Lock();
        try
        {
            return m_Dictionary.TryAdd(key, value);
        }
        catch (Exception e)
        {
             GameDebug.LogException(e); 
             return false;
        }
        finally
        {
            m_Lock.UnLock();
        }
    }

    #endif

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public bool Remove(TKey key)
    {
        m_Lock.Lock();
        try
        {
            if (m_Dictionary.ContainsKey(key))
            {
                return m_Dictionary.Remove(key);
            }
            else
            {
                return false;
            }
        }
        catch (Exception e)
        {
            GameDebug.LogException(e);
            return false;
        }
        finally
        {
            m_Lock.UnLock();
        }
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public bool TryGetValue(TKey key, out TValue value)
    {
        m_Lock.Lock();
        try
        {
            return m_Dictionary.TryGetValue(key, out value);
        }
        catch (Exception e)
        {
            value = default(TValue);
            GameDebug.LogException(e);
            return false;
        }
        finally
        {
            m_Lock.UnLock();
        }
    }

    
    public TValue this[TKey key]
    {
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        get
        {
            m_Lock.Lock();
            try
            {
                return m_Dictionary[key];
            }
            catch (Exception e)
            {
                GameDebug.LogException(e);
                return default(TValue);
            }
            finally
            {
                m_Lock.UnLock();
            }
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        set
        {
            m_Lock.Lock();
            try
            {
                if (m_Dictionary.ContainsKey(key))
                {
                    m_Dictionary.Remove(key);
                }
                m_Dictionary[key] = value;
            }
            catch (Exception e)
            {
                GameDebug.LogException(e);
            }
            finally
            {
                m_Lock.UnLock();
            }
        }
    }
    
    public bool ContainsKey(TKey key)
    {
        m_Lock.Lock();
        try
        {
            return m_Dictionary.ContainsKey(key);
        }
        catch (Exception e)
        {
            GameDebug.LogException(e);
            return false;
        }
        finally
        {
            m_Lock.UnLock();
        }
    }

    public Dictionary<TKey, TValue>.ValueCollection Values
    {
        get
        {
            m_Lock.Lock();
            try
            {
                return m_Dictionary.Values;
            }
            catch (Exception e)
            {
                GameDebug.LogException(e);
                return null;
            }
            finally
            {
                m_Lock.UnLock();
            }
        }
    }
    public void Foreach(Action<KeyValuePair<TKey, TValue>> action)
    {
        m_Lock.Lock();
        try
        {
            foreach(KeyValuePair<TKey, TValue> pair in m_Dictionary)
            {
                action?.Invoke(pair);
            }
        }
        catch (Exception e)
        {
            GameDebug.LogException(e);
        }
        finally
        {
            m_Lock.UnLock();
        }
        
    }
}